const { ccclass, property } = cc._decorator;

/**
 * Toast 轻提示基类
 * 在页面中间弹出黑色半透明提示，用于消息通知、加载提示、操作结果提示等场景。
 * @see ToastBase.ts 
 */
@ccclass
export default class ToastBase extends cc.Component {


    @property({ type: cc.Label, tooltip: CC_DEV && '消息' })
    public msg: cc.Label = null;

    /** 动画时长 */
    public animTime: number = 3;


    /** Toast消息 */
    protected msgString: String = null;

    /** Toast流程结束回调（注意：该回调为 ToastManager 专用，重写 hide 函数时记得调用该回调） */
    protected finishCallback: Function = null;

    /**
     * Toast已完全展示（子类请重写此函数以实现自定义逻辑）
     */
    protected onShow(): void {
    }

    /**
     * Toast已完全隐藏（子类请重写此函数以实现自定义逻辑）
     */
    protected onHide(): void {
        this.node.off(cc.Node.EventType.TOUCH_END, this.toastClick, this);
    }


    /**
     * Toast展示动画（子类请重写此函数以实现自定义逻辑）
     */
    public async beforeShow(): Promise<any> {
        return new Promise((resolve, reject) => {
            // 播放背景动画
            cc.tween(this.node)
                .to(this.animTime * 0.8, { opacity: 255 })
                .call(() => {
                    resolve();
                })
                .start();
        })
    }

    /**
     * Toast显示
     * @param msg 显示内容
     */
    public async show(msg?: String) {
        // 储存选项
        this.msgString = msg;
        // 重置节点
        this.node.opacity = 0;
        this.node.active = true;
        // 初始化
        this.init(this.msgString);
        // 更新样式
        this.updateDisplay(this.msgString);
        await this.beforeShow();
        this.onShow();
        await this.beforeClose();
        this.hide();
    }

    /**
     * Toast关闭动画（子类请重写此函数以实现自定义逻辑）
     */
    public async beforeClose() {
        return new Promise((resolve, reject) => {
            cc.tween(this.node)
                .to(this.animTime * 0.8, { opacity: 0 })
                .call(() => {
                    resolve();
                })
                .start();
        })
    }

    /**
     * Toast隐藏
     */
    public async hide() {
        // 关闭节点
        this.node.active = false;
        // Toast已完全隐藏（动画完毕）
        this.onHide();
        // Toast关闭完成回调（该回调为 ToastManager 专用）
        // 注意：重写 hide 函数时记得调用该回调
        if (this.finishCallback) {
            this.finishCallback();
            this.finishCallback = null;
        }
    }

    /**
     * 初始化（子类请重写此函数以实现自定义逻辑）
     */
    protected init(msg: String): void {
        this.node.on(cc.Node.EventType.TOUCH_END, this.toastClick, this);
    }

    /**
     * 更新样式（子类请重写此函数以实现自定义样式）
     * @param msg 消息
     */
    protected updateDisplay(msg: any): void {
        this.msg.string = msg;
    }

    /** 点击toast组件提前隐藏 */
    private toastClick() {
        this.hide();
    }

    /**
     * 设置Toast完成回调（该回调为 ToastManager 专用）
     * @param callback 回调
     */
    public setFinishCallback(callback: Function): void {
        if (this.finishCallback) {
            return cc.warn('[ToastBase]', '无法重复指定完成回调！');
        }
        this.finishCallback = callback;
    }
}
